﻿using System;
using System.ComponentModel;
using System.Reflection;

namespace KLS.PPDS.Utilities.Attributes
{
    public static class PropertyHelper
    {
        private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;

        public static bool IsInt16(this PropertyInfo property)
        {
            return property.PropertyType == typeof(Int16);
        }

        public static bool IsInt32(this PropertyInfo property)
        {
            return property.PropertyType == typeof(Int32);
        }

        public static bool IsInt64(this PropertyInfo property)
        {
            return property.PropertyType == typeof(Int64);
        }

        public static bool IsLong(this PropertyInfo property)
        {
            return property.PropertyType == typeof(long);
        }

        public static bool IsDecimal(this PropertyInfo property)
        {
            return property.PropertyType == typeof(decimal);
        }

        public static bool IsDouble(this PropertyInfo property)
        {
            return property.PropertyType == typeof(double);
        }

        public static bool IsFloat(this PropertyInfo property)
        {
            return property.PropertyType == typeof(float);
        }

        public static bool IsBool(this PropertyInfo property)
        {
            return property.PropertyType == typeof(bool);
        }

        public static bool IsString(this PropertyInfo property)
        {
            return property.PropertyType == typeof(String);
        }


        private static object GetPropertyValue(this object obj, PropertyInfo property)
        {
            return property.GetValue(obj, null);
        }

        private static void SetPropertyValue(this object obj, PropertyInfo property, object value)
        {
            property.SetValue(obj, value, null);
        }

        private static void SetStringValue(this object obj, PropertyInfo property, DefaultValueAttribute attribute)
        {
            var value = obj.GetPropertyValue(property); //  Convert.ToString().Trim();
            if (value == null)
            {
                obj.SetPropertyValue(property, attribute.Value);
            }
        }

        //private static void SetStringValue(this object obj, PropertyInfo property, StringValueAttribute attribute)
        //{
        //    obj.SetStringValue(property, (DefaultValueAttribute)attribute);

        //    var value = Convert.ToString(obj.GetPropertyValue(property));
        //    if (attribute.MaxLength > 0 && !string.IsNullOrEmpty(value) && value.Length > attribute.MaxLength)
        //    {
        //        obj.SetPropertyValue(property, value.Substring(0, attribute.MaxLength));
        //    }
        //}

        //private static void SetInt32Value(this object obj, PropertyInfo property, DefaultValueAttribute attribute)
        //{
        //    var value = Convert.ToInt32(obj.GetPropertyValue(property));
        //    if (value == 0)
        //    {
        //        obj.SetPropertyValue(property, attribute.Value);
        //    }
        //}

        //private static void SetInt32RangeValue(this object obj, PropertyInfo property, RangeValueAttribute attribute)
        //{
        //    var value = Convert.ToInt32(obj.GetPropertyValue(property));
        //    if (value < attribute.Min.ToInt32() || value > attribute.Max.ToInt32())
        //    {
        //        obj.SetPropertyValue(property, attribute.Value);
        //    }
        //}

        //public static void DefaultValue(this object obj)
        //{
        //    if (obj != null)
        //    {
        //        var properties = obj.GetType().GetProperties(PropertyHelper.Flags).Where(x => x.CanRead && x.CanWrite).ToArray();
        //        foreach (var property in properties)
        //        {
        //            object attribute = property.GetCustomAttributes(typeof(DefaultValueAttribute), false).FirstOrDefault();
        //            if (attribute != null)
        //            {
        //                if (attribute.GetType() == typeof(DefaultValueAttribute))
        //                {
        //                    if (property.IsString())
        //                    {
        //                        obj.SetStringValue(property, (DefaultValueAttribute)attribute);
        //                    }
        //                    else if (property.IsInt32())
        //                    {
        //                        obj.SetInt32Value(property, (DefaultValueAttribute)attribute);
        //                    }
        //                    else
        //                    {
        //                        throw new NotImplementedException();
        //                    }
        //                }
        //                else if (attribute.GetType() == typeof(StringValueAttribute))
        //                {
        //                    obj.SetStringValue(property, (StringValueAttribute)attribute);
        //                }
        //                else if (attribute.GetType() == typeof(RangeValueAttribute))
        //                {
        //                    if (property.IsInt32())
        //                    {
        //                        obj.SetInt32RangeValue(property, (RangeValueAttribute)attribute);
        //                    }
        //                    else
        //                    {
        //                        throw new NotImplementedException();
        //                    }
        //                }
        //                else
        //                {
        //                    throw new NotImplementedException();
        //                }
        //            }
        //        }
        //    }
        //}

        public static void CopyPropertyValue<TSource, TDestination>(this TSource source, TDestination destination)
        {
            if (source != null)
            {
                if (destination == null)
                {
                    destination = Activator.CreateInstance<TDestination>();
                }

                var sourceType = source.GetType();
                var destinationType = destination.GetType();

                var destinationProperties = destinationType.GetProperties(PropertyHelper.Flags);
                foreach (var destinationProperty in destinationProperties)
                {
                    if (destinationProperty.CanWrite)
                    {
                        var sourceProperty = sourceType.GetProperty(destinationProperty.Name, Flags);
                        if (sourceProperty != null && sourceProperty.CanRead)
                        {
                            destination.SetPropertyValue(destinationProperty, source.GetPropertyValue(sourceProperty));
                        }
                    }
                }
            }
        }
    }
}
